package com.yupi.springbootinit.statemachine.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yupi.springbootinit.statemachine.dto.StateMachineConfigQueryRequest;
import com.yupi.springbootinit.statemachine.dto.StateMachineConfigUpdateRequest;
import com.yupi.springbootinit.statemachine.entity.StateMachineConfig;
import com.yupi.springbootinit.statemachine.mapper.StateMachineConfigMapper;
import com.yupi.springbootinit.statemachine.service.StateMachineConfigService;
import com.yupi.springbootinit.utils.SqlUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 状态机配置服务实现
 */
@Slf4j
@Service
public class StateMachineConfigServiceImpl extends ServiceImpl<StateMachineConfigMapper, StateMachineConfig> 
        implements StateMachineConfigService {
    
    /**
     * 默认配置值映射
     */
    private static final Map<String, String> DEFAULT_CONFIG_VALUES = new HashMap<>();
    
    static {
        initializeDefaultConfigs();
    }
    
    /**
     * 初始化默认配置
     */
    private static void initializeDefaultConfigs() {
        // 状态转换超时配置
        DEFAULT_CONFIG_VALUES.put("state.transition.timeout", "30000");
        DEFAULT_CONFIG_VALUES.put("state.transition.retry.max", "3");
        DEFAULT_CONFIG_VALUES.put("state.transition.retry.interval", "5000");
        
        // 权限配置
        DEFAULT_CONFIG_VALUES.put("permission.check.enabled", "true");
        DEFAULT_CONFIG_VALUES.put("permission.cache.ttl", "3600");
        
        // 通知配置
        DEFAULT_CONFIG_VALUES.put("notification.enabled", "true");
        DEFAULT_CONFIG_VALUES.put("notification.async", "true");
        DEFAULT_CONFIG_VALUES.put("notification.retry.max", "3");
        
        // 审计配置
        DEFAULT_CONFIG_VALUES.put("audit.enabled", "true");
        DEFAULT_CONFIG_VALUES.put("audit.detail.enabled", "true");
        DEFAULT_CONFIG_VALUES.put("audit.retention.days", "90");
        
        // 自动推进配置
        DEFAULT_CONFIG_VALUES.put("auto.progress.enabled", "true");
        DEFAULT_CONFIG_VALUES.put("auto.progress.interval", "60000");
        DEFAULT_CONFIG_VALUES.put("auto.progress.batch.size", "100");
        
        // 业务规则配置
        DEFAULT_CONFIG_VALUES.put("rule.engine.enabled", "true");
        DEFAULT_CONFIG_VALUES.put("rule.validation.strict", "true");
        DEFAULT_CONFIG_VALUES.put("rule.cache.enabled", "true");
    }
    
    @Override
    public IPage<StateMachineConfig> queryConfigs(StateMachineConfigQueryRequest request) {
        QueryWrapper<StateMachineConfig> queryWrapper = buildQueryWrapper(request);
        
        // 分页查询
        Page<StateMachineConfig> page = new Page<>(request.getCurrent(), request.getPageSize());
        
        // 排序
        if (StringUtils.hasText(request.getSortField())) {
            boolean isAsc = "asc".equalsIgnoreCase(request.getSortOrder());
            if (SqlUtils.validSortField(request.getSortField())) {
                queryWrapper.orderBy(true, isAsc, request.getSortField());
            }
        } else {
            // 默认按配置键排序
            queryWrapper.orderByAsc("config_key");
        }
        
        IPage<StateMachineConfig> result = this.page(page, queryWrapper);
        
        log.debug("查询状态机配置: 条件={}, 结果数={}", request.getEntityType(), result.getRecords().size());
        
        return result;
    }
    
    @Override
    @Cacheable(value = "statemachine:config:type", key = "#entityType")
    public List<StateMachineConfig> getConfigsByStateType(String entityType) {
        QueryWrapper<StateMachineConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("entity_type", entityType)
                   .eq("enabled", true)
                   .orderByAsc("config_key");
        
        List<StateMachineConfig> configs = this.list(queryWrapper);
        
        log.debug("获取实体类型[{}]的配置: 数量={}", entityType, configs.size());
        
        return configs;
    }
    
    @Override
    @Cacheable(value = "statemachine:config:key", key = "#configKey")
    public StateMachineConfig getConfigByKey(String configKey) {
        QueryWrapper<StateMachineConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("config_key", configKey)
                   .eq("enabled", true);
        
        StateMachineConfig config = this.getOne(queryWrapper);
        
        log.debug("获取配置[{}]: {}", configKey, config != null ? "存在" : "不存在");
        
        return config;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"statemachine:config:key", "statemachine:config:type", "statemachine:config:all"}, allEntries = true)
    public boolean updateConfig(StateMachineConfigUpdateRequest request, Long userId) {
        if (request == null || !StringUtils.hasText(request.getConfigKey())) {
            log.warn("更新配置请求参数无效");
            return false;
        }
        
        // 验证配置值
        if (!validateConfigValue(request.getConfigKey(), request.getConfigValue())) {
            log.warn("配置值验证失败: key={}, value={}", request.getConfigKey(), request.getConfigValue());
            return false;
        }
        
        // 查找现有配置
        StateMachineConfig existingConfig = getConfigByKey(request.getConfigKey());
        
        if (existingConfig != null) {
            // 更新现有配置
            existingConfig.setConfigValue(request.getConfigValue());
            existingConfig.setDescription(request.getDescription());
            existingConfig.setUpdateTime(LocalDateTime.now());
            existingConfig.setUpdaterId(userId);
            
            boolean success = this.updateById(existingConfig);
            
            if (success) {
                log.info("更新配置成功: key={}, value={}, userId={}", 
                    request.getConfigKey(), request.getConfigValue(), userId);
            } else {
                log.error("更新配置失败: key={}", request.getConfigKey());
            }
            
            return success;
        } else {
            // 创建新配置
            StateMachineConfig newConfig = new StateMachineConfig();
            newConfig.setConfigName(request.getConfigName());
            newConfig.setConfigKey(request.getConfigKey());
            newConfig.setConfigValue(request.getConfigValue());
            newConfig.setEntityType(request.getEntityType());
            newConfig.setConfigType(request.getConfigType());
            newConfig.setDescription(request.getDescription());
            newConfig.setEnabled(true);
            newConfig.setPriority(request.getPriority() != null ? request.getPriority() : 0);
            newConfig.setVersion(1);
            newConfig.setCreateTime(LocalDateTime.now());
            newConfig.setUpdateTime(LocalDateTime.now());
            newConfig.setCreatorId(userId);
            newConfig.setUpdaterId(userId);
            
            boolean success = this.save(newConfig);
            
            if (success) {
                log.info("创建配置成功: key={}, value={}, userId={}", 
                    request.getConfigKey(), request.getConfigValue(), userId);
            } else {
                log.error("创建配置失败: key={}", request.getConfigKey());
            }
            
            return success;
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"statemachine:config:key", "statemachine:config:type", "statemachine:config:all"}, allEntries = true)
    public boolean batchUpdateConfigs(List<StateMachineConfig> configs, Long userId) {
        if (CollectionUtils.isEmpty(configs)) {
            log.warn("批量更新配置列表为空");
            return false;
        }
        
        try {
            for (StateMachineConfig config : configs) {
                // 验证配置值
                if (!validateConfigValue(config.getConfigKey(), config.getConfigValue())) {
                    log.warn("配置值验证失败: key={}, value={}", config.getConfigKey(), config.getConfigValue());
                    continue;
                }
                
                config.setUpdateTime(LocalDateTime.now());
                config.setUpdaterId(userId);
            }
            
            boolean success = this.updateBatchById(configs);
            
            if (success) {
                log.info("批量更新配置成功: 数量={}, userId={}", configs.size(), userId);
            } else {
                log.error("批量更新配置失败: 数量={}", configs.size());
            }
            
            return success;
        } catch (Exception e) {
            log.error("批量更新配置异常", e);
            return false;
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"statemachine:config:key", "statemachine:config:type", "statemachine:config:all"}, allEntries = true)
    public boolean resetConfigToDefault(String configKey, Long userId) {
        if (!StringUtils.hasText(configKey)) {
            log.warn("重置配置的键为空");
            return false;
        }
        
        String defaultValue = DEFAULT_CONFIG_VALUES.get(configKey);
        if (defaultValue == null) {
            log.warn("配置[{}]没有默认值", configKey);
            return false;
        }
        
        StateMachineConfig config = getConfigByKey(configKey);
        if (config == null) {
            log.warn("配置[{}]不存在", configKey);
            return false;
        }
        
        config.setConfigValue(defaultValue);
        config.setUpdateTime(LocalDateTime.now());
        config.setUpdaterId(userId);
        
        boolean success = this.updateById(config);
        
        if (success) {
            log.info("重置配置成功: key={}, defaultValue={}, userId={}", 
                configKey, defaultValue, userId);
        } else {
            log.error("重置配置失败: key={}", configKey);
        }
        
        return success;
    }
    
    @Override
    @Cacheable(value = "statemachine:config:all")
    public List<StateMachineConfig> getAllActiveConfigs() {
        QueryWrapper<StateMachineConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("enabled", true)
                   .orderByAsc("entity_type", "config_key");
        
        List<StateMachineConfig> configs = this.list(queryWrapper);
        
        log.debug("获取所有有效配置: 数量={}", configs.size());
        
        return configs;
    }
    
    @Override
    @CacheEvict(value = {"statemachine:config:key", "statemachine:config:type", "statemachine:config:all"}, allEntries = true)
    public void refreshConfigCache() {
        log.info("刷新状态机配置缓存");
    }
    
    @Override
    public boolean validateConfigValue(String configKey, String configValue) {
        if (!StringUtils.hasText(configKey) || !StringUtils.hasText(configValue)) {
            return false;
        }
        
        try {
            // 根据配置键类型进行验证
            if (configKey.contains("timeout") || configKey.contains("interval") || 
                configKey.contains("max") || configKey.contains("ttl") || 
                configKey.contains("days") || configKey.contains("size")) {
                // 数值类型配置
                long value = Long.parseLong(configValue);
                return value >= 0;
            } else if (configKey.contains("enabled")) {
                // 布尔类型配置
                return "true".equalsIgnoreCase(configValue) || "false".equalsIgnoreCase(configValue);
            } else {
                // 字符串类型配置
                return configValue.length() <= 500;
            }
        } catch (NumberFormatException e) {
            log.warn("配置值格式错误: key={}, value={}", configKey, configValue);
            return false;
        }
    }
    
    /**
     * 构建查询条件
     */
    private QueryWrapper<StateMachineConfig> buildQueryWrapper(StateMachineConfigQueryRequest request) {
        QueryWrapper<StateMachineConfig> queryWrapper = new QueryWrapper<>();
        
        if (StringUtils.hasText(request.getConfigKey())) {
            queryWrapper.like("config_key", request.getConfigKey());
        }
        
        if (StringUtils.hasText(request.getEntityType())) {
            queryWrapper.eq("entity_type", request.getEntityType());
        }
        
        if (StringUtils.hasText(request.getConfigName())) {
            queryWrapper.like("config_name", request.getConfigName());
        }
        
        if (request.getEnabled() != null) {
            queryWrapper.eq("enabled", request.getEnabled());
        }
        
        if (StringUtils.hasText(request.getStartTime())) {
            queryWrapper.ge("create_time", request.getStartTime());
        }
        
        if (StringUtils.hasText(request.getEndTime())) {
            queryWrapper.le("create_time", request.getEndTime());
        }
        
        if (StringUtils.hasText(request.getKeyword())) {
            queryWrapper.and(wrapper -> wrapper
                    .like("config_name", request.getKeyword())
                    .or()
                    .like("description", request.getKeyword()));
        }
        
        return queryWrapper;
    }
}